/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package SemanticoPacote;

import SemanticoPacote.TratamentoErroSemantico.ErroSemantico;
import compilador_full.TabelaSimbolos;

/**
 *
 * @author Jomas
 */    
    //<chamadaDeFuncao> ::= <nome> ( [ <parametrosChamadaDeFuncao>
    //{ , <parametrosChamadaDeFuncao>} ] );

    //<parametrosChamadaDeFuncao> := ( ( * | &) <nome> { [ (<numero> | <nome>) ] } | <numero> |
    //<boolean> | ‘ <caracter> ’ | <expAritmetica> )

public class chamadaDeFuncao {    

    private TabelaSimbolos tabelaSimbolos;
    
    public chamadaDeFuncao(TabelaSimbolos tabelaSimbolos)
    {
        this.tabelaSimbolos = tabelaSimbolos;        
    }

     public void chamaFuncao(String escopo){
         
         //ArrayList<String> parametros = new ArrayList<String>();
         //parametros = tabelaSimbolos.procuraParametrosDeFuncao(nomeMetodo);

         int posicaoArrayParametros = 0;
         String nomeMetodo = tabelaSimbolos.getLookahead();
         tabelaSimbolos.soConsome(); //consome o identificador, nome do metodo
         tabelaSimbolos.soConsome(); //consome o (              

         while (!(tabelaSimbolos.getLookahead().equals(")"))){//até achar o parenteses final, faça


             String parametroDeclarado = tabelaSimbolos.procuraParametrosDeFuncao(nomeMetodo).get(posicaoArrayParametros);

             
            if((tabelaSimbolos.getTipo().equals("numero") || tabelaSimbolos.getTipo().equals("identificador"))&& (tabelaSimbolos.superLookahead(1).equals("+") || tabelaSimbolos.superLookahead(1).equals("-") ||
                     tabelaSimbolos.superLookahead(1).equals("*") || tabelaSimbolos.superLookahead(1).equals("/")))
                {

                        ExpressaoAritmetica expArit2 = new ExpressaoAritmetica();
                        expArit2.expAritmetica(tabelaSimbolos, escopo, "int");//consome expressao aritmetica
             }
            else if(tabelaSimbolos.getTipo().equals("identificador")){

                //Verifica se a variável foi declarada
                if (!tabelaSimbolos.validaNome(escopo, tabelaSimbolos.getLookahead())) {//verifica se variavel dentro do parametro de função está declarada
                    if(!(Utils.tipoValor(tabelaSimbolos.getLookahead()).equals("char") && parametroDeclarado.equals("char")) &&
                            (!((Utils.tipoValor(tabelaSimbolos.getLookahead()).equals("boolean"))) && ((parametroDeclarado.equals("true")) || parametroDeclarado.equals("false")))){
                            System.out.println("Linha: " + tabelaSimbolos.getLinha() + " ERRO SEMANTICO - Variável " + tabelaSimbolos.getLookahead() + " não declarada");
                            ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha " +tabelaSimbolos.getLinha() + ". Descrição: Variável não já foi declarada");
                    }
                    // Esse segundo if existe, pois é necessário verificar se o identificador é um char. caso seja um char, o que a função irá receber como parâmetro seja um char: "a"
                    // é necessário tratar dessa forma. pq ele considera o a como identificador, já que o léximo não add aspas na tabela de simbolos. E tb verificar a questão do vir o identificador
                    // true ou false. 
                }

                //Verifica o tipo da variável declarada e o tipo passado como parâmetro
                if(!tabelaSimbolos.RetornaTipoDeLocalDeclarada(tabelaSimbolos.getLookahead(), escopo).equals(parametroDeclarado)){
                    if(!(Utils.tipoValor(tabelaSimbolos.getLookahead()).equals("char") && parametroDeclarado.equals("char")) &&
                            (!((Utils.tipoValor(tabelaSimbolos.getLookahead()).equals("boolean"))) && ((parametroDeclarado.equals("true")) || parametroDeclarado.equals("false"))));
                        ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha " +tabelaSimbolos.getLinha() + ". Descrição: Variável incompatível com tipo");
                }

                if(tabelaSimbolos.procuraParametrosDeFuncao(nomeMetodo).get(posicaoArrayParametros + 1).equals("*")){
                    System.out.println("Linha: " + tabelaSimbolos.getLinha() + "- ERRO SEMANTICO - Esperado & na variável " + tabelaSimbolos.getLookahead() );
                    ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha " +tabelaSimbolos.getLinha() + ". Descrição: Esperado o & na variável");
                    posicaoArrayParametros++;
                }
                posicaoArrayParametros++;
             }

             else if(tabelaSimbolos.getLookahead().equals("*")){

                tabelaSimbolos.soConsome(); // consome o *
                //Verifica o tipo da variável declarada e o tipo passado como parâmetro
                if(!tabelaSimbolos.RetornaTipoDeLocalDeclarada(tabelaSimbolos.getLookahead(), escopo).equals(parametroDeclarado)){
                    System.out.println("Linha: " + tabelaSimbolos.getLinha() + "- ERRO SEMANTICO - Variável " + tabelaSimbolos.getLookahead() + " com tipo incompativel");
                    ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha " +tabelaSimbolos.getLinha() + ". Descrição: Variável incompatível com tipo");
                }

                //Verifica se a variável foi declarada
                if (!tabelaSimbolos.validaNome(escopo, tabelaSimbolos.getLookahead())) {//verifica se variavel dentro do parametro de função está declarada
                    System.out.println("Linha: " + tabelaSimbolos.getLinha() + " ERRO SEMANTICO - Variável " + tabelaSimbolos.getLookahead() + " não declarada");
                    ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha " +tabelaSimbolos.getLinha() + ". Descrição: Variável não declarada");
                }

                // Verifica se na declaração foi colocado o &
                if(!tabelaSimbolos.procuraParametrosDeFuncao(nomeMetodo).get(++posicaoArrayParametros).equals("&")){
                    System.out.println("Linha: " + tabelaSimbolos.getLinha() + "- ERRO SEMANTICO - Esperado & na variável " + tabelaSimbolos.getLookahead());
                    ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha " +tabelaSimbolos.getLinha() + ". Descrição: Esperado & na variável");
                }                
            }
             else if(tabelaSimbolos.getLookahead().equals("&")){
                
                tabelaSimbolos.soConsome(); // consome o &
                
                //Verifica o tipo da variável declarada e o tipo passado como parâmetro
                if(!tabelaSimbolos.RetornaTipoDeLocalDeclarada(tabelaSimbolos.getLookahead(), escopo).equals(parametroDeclarado)){
                    System.out.println("Linha: " + tabelaSimbolos.getLinha() + "- ERRO SEMANTICO - Variável " + tabelaSimbolos.getLookahead() + " com tipo incompativel");
                    ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha " +tabelaSimbolos.getLinha() + ". Descrição: Variável incompatível com tipo");
                }

                //Verifica se a variável foi declarada
                if (!tabelaSimbolos.validaNome(escopo, tabelaSimbolos.getLookahead())) {//verifica se variavel dentro do parametro de função está declarada
                    System.out.println("Linha: " + tabelaSimbolos.getLinha() + " ERRO SEMANTICO - Variável " + tabelaSimbolos.getLookahead() + " não declarada");
                    ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha " +tabelaSimbolos.getLinha() + ". Descrição: Variável não declarada");
                }

                // Verifica se na declaração foi colocado o *
                if(!tabelaSimbolos.procuraParametrosDeFuncao(nomeMetodo).get(++posicaoArrayParametros).equals("*")){
                    System.out.println("Linha: " + tabelaSimbolos.getLinha() + "- ERRO SEMANTICO - Esperado * na variável " + tabelaSimbolos.getLookahead());
                    ErroSemantico.getInstance().getTabelaErros().add("Erro Semântico na linha " +tabelaSimbolos.getLinha() + ". Descrição: Esperado * na variável");
                } 
            }

             //tabelaSimbolos.soConsome();//consome identificador, nome da variavel de parametro de funcao
             
             if(tabelaSimbolos.getLookahead().equals(",")){
                 tabelaSimbolos.soConsome();//consome a virgula
             }
        }

         tabelaSimbolos.soConsome(); // consome o )
         //tabelaSimbolos.soConsome(); // consome o ;
     }

    boolean chamaFuncao() {
        throw new UnsupportedOperationException("Not yet implemented");
    }
}
